From 564a3bf276a54124229617f57d1940c2e8d17cf0 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 6 Apr 2006 11:34:14 +0100 Subject: [PATCH] More simplifications to blkback: 1. Remove blkif->status field as it's really not needed. 2. Simplify connection logic. 3. Get rid of atomic_t io_pending. There's no need for atomic r-m-w updates to the work-to-do flag, so replace with an integer and add barriers where serialisation is required. Signed-off-by: Keir Fraser --- .../drivers/xen/blkback/blkback.c | 29 ++++++++-------- .../drivers/xen/blkback/common.h | 6 ++-- .../drivers/xen/blkback/interface.c | 4 --- .../drivers/xen/blkback/xenbus.c | 33 ++++++------------- 4 files changed, 27 insertions(+), 45 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c b/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c index 477cab4bc6..4faf117069 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c @@ -225,16 +225,16 @@ int blkif_schedule(void *arg) while (!kthread_should_stop()) { wait_event_interruptible( blkif->wq, - atomic_read(&blkif->io_pending) || - kthread_should_stop()); + blkif->waiting_reqs || kthread_should_stop()); wait_event_interruptible( pending_free_wq, - !list_empty(&pending_free) || - kthread_should_stop()); + !list_empty(&pending_free) || kthread_should_stop()); + + blkif->waiting_reqs = 0; + smp_mb(); /* clear flag *before* checking for work */ - atomic_set(&blkif->io_pending, 0); if (do_block_io_op(blkif)) - atomic_inc(&blkif->io_pending); + blkif->waiting_reqs = 1; unplug_queue(blkif); if (log_stats && time_after(jiffies, blkif->st_print)) @@ -287,12 +287,15 @@ static int end_block_io_op(struct bio *bio, unsigned int done, int error) * NOTIFICATION FROM GUEST OS. */ -irqreturn_t blkif_be_int(int irq, void *dev_id, struct pt_regs *regs) +void blkif_notify_work(blkif_t *blkif) { - blkif_t *blkif = dev_id; - - atomic_inc(&blkif->io_pending); + blkif->waiting_reqs = 1; wake_up(&blkif->wq); +} + +irqreturn_t blkif_be_int(int irq, void *dev_id, struct pt_regs *regs) +{ + blkif_notify_work(dev_id); return IRQ_HANDLED; } @@ -512,10 +515,8 @@ static void make_response(blkif_t *blkif, unsigned long id, } spin_unlock_irqrestore(&blkif->blk_ring_lock, flags); - if (more_to_do) { - atomic_inc(&blkif->io_pending); - wake_up(&blkif->wq); - } + if (more_to_do) + blkif_notify_work(blkif); if (notify) notify_remote_via_irq(blkif->irq); } diff --git a/linux-2.6-xen-sparse/drivers/xen/blkback/common.h b/linux-2.6-xen-sparse/drivers/xen/blkback/common.h index 502a02c6b8..58939d6ab2 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blkback/common.h +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/common.h @@ -72,7 +72,6 @@ typedef struct blkif_st { /* Back pointer to the backend_info. */ struct backend_info *be; /* Private fields. */ - enum { DISCONNECTED, CONNECTED } status; #ifdef CONFIG_XEN_BLKDEV_TAP_BE /* Is this a blktap frontend */ unsigned int is_blktap; @@ -82,7 +81,7 @@ typedef struct blkif_st { wait_queue_head_t wq; struct task_struct *xenblkd; - atomic_t io_pending; + unsigned int waiting_reqs; request_queue_t *plug; /* statistics */ @@ -130,11 +129,10 @@ void blkif_interface_init(void); void blkif_xenbus_init(void); +void blkif_notify_work(blkif_t *blkif); irqreturn_t blkif_be_int(int irq, void *dev_id, struct pt_regs *regs); int blkif_schedule(void *arg); -void update_blkif_status(blkif_t *blkif); - #endif /* __BLKIF__BACKEND__COMMON_H__ */ /* diff --git a/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c b/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c index 75b9f74b0b..c220efcf4b 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c @@ -45,7 +45,6 @@ blkif_t *alloc_blkif(domid_t domid) memset(blkif, 0, sizeof(*blkif)); blkif->domid = domid; - blkif->status = DISCONNECTED; spin_lock_init(&blkif->blk_ring_lock); atomic_set(&blkif->refcnt, 1); init_waitqueue_head(&blkif->wq); @@ -138,9 +137,6 @@ int blkif_map(blkif_t *blkif, unsigned long shared_page, unsigned int evtchn) blkif->irq = bind_evtchn_to_irqhandler( blkif->evtchn, blkif_be_int, 0, "blkif-backend", blkif); - /* We're potentially connected now */ - update_blkif_status(blkif); - return 0; } diff --git a/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c b/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c index 636caefdd8..d0ec094d66 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c @@ -17,7 +17,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - #include #include #include @@ -25,36 +24,33 @@ #include "common.h" #undef DPRINTK -#define DPRINTK(fmt, args...) \ - pr_debug("blkback/xenbus (%s:%d) " fmt ".\n", __FUNCTION__, __LINE__, ##args) - +#define DPRINTK(fmt, args...) \ + pr_debug("blkback/xenbus (%s:%d) " fmt ".\n", \ + __FUNCTION__, __LINE__, ##args) struct backend_info { struct xenbus_device *dev; blkif_t *blkif; struct xenbus_watch backend_watch; - unsigned major; unsigned minor; char *mode; }; - -static void maybe_connect(struct backend_info *); static void connect(struct backend_info *); static int connect_ring(struct backend_info *); static void backend_changed(struct xenbus_watch *, const char **, unsigned int); -void update_blkif_status(blkif_t *blkif) +static void update_blkif_status(blkif_t *blkif) { - if(blkif->irq && blkif->vbd.bdev) { - blkif->status = CONNECTED; - (void)blkif_be_int(0, blkif, NULL); + if (blkif->irq && blkif->vbd.bdev && + (blkif->be->dev->state != XenbusStateConnected)) { + connect(blkif->be); + blkif_notify_work(blkif); } - maybe_connect(blkif->be); } @@ -91,7 +87,6 @@ static int blkback_remove(struct xenbus_device *dev) be->backend_watch.node = NULL; } if (be->blkif) { - be->blkif->status = DISCONNECTED; if (be->blkif->xenblkd) kthread_stop(be->blkif->xenblkd); blkif_put(be->blkif); @@ -185,8 +180,8 @@ static void backend_changed(struct xenbus_watch *watch, return; } - if (be->major && be->minor && - (be->major != major || be->minor != minor)) { + if ((be->major || be->minor) && + ((be->major != major) || (be->minor != minor))) { printk(KERN_WARNING "blkback: changing physical device (from %x:%x to " "%x:%x) not supported.\n", be->major, be->minor, @@ -290,14 +285,6 @@ static void frontend_changed(struct xenbus_device *dev, /* ** Connection ** */ -static void maybe_connect(struct backend_info *be) -{ - if ((be->major != 0 || be->minor != 0) && - be->blkif->status == CONNECTED) - connect(be); -} - - /** * Write the physical details regarding the block device to the store, and * switch to Connected state. -- 2.30.2